/*
 *  GameSystem.cpp
 *  vorpal
 *
 *  Created by rwebb on 4/05/08.
 *
 */

#include "atto.h"
#include "System.h"
#include "GameSystem.h"
#include "VM.h"
#include "Compiler.h"

using namespace Vorpal;

void GameSystem::Compile(const char *sourcePath){
	if(!sourcePath){ return; }
	if(code){
		delete[] code;
	}

	Compiler c;
	c.EnableDebugInfo(true);
	Require(c.Compile(sourcePath));

	code = new Cell[c.Size()];
	c.Get(code, c.Size());
	
	puts("-----------");
	printf("code[%u]:\n", c.Size());
	// Disassemble(PrintInstruction, code);
	puts("-----------");		
}

bool GameSystem::Receive(Message msg, uint numArgs, VM *vm){
	switch(msg){
		case msg_redraw: {
			atto_redraw();
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_text: {
			Assert(numArgs == 4);
			atto_string(int(vm->FromTop(2)->ToNumber()), int(vm->FromTop(1)->ToNumber()), vm->FromTop(0)->ToString().c_str());
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_gif: {
			Assert(numArgs == 4);
			atto_gif(int(vm->FromTop(2)->ToNumber()), int(vm->FromTop(1)->ToNumber()), vm->FromTop(0)->ToString().c_str());
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_arc: {
			Assert(numArgs == 7);
			atto_arc(int(vm->FromTop(5)->ToNumber()), int(vm->FromTop(4)->ToNumber()), 
					 int(vm->FromTop(3)->ToNumber()), int(vm->FromTop(2)->ToNumber()), 
					 int(vm->FromTop(1)->ToNumber()), int(vm->FromTop(0)->ToNumber()));
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_frame: {
			Assert(numArgs == 5);
			atto_frame(int(vm->FromTop(3)->ToNumber()), int(vm->FromTop(2)->ToNumber()), int(vm->FromTop(1)->ToNumber()), int(vm->FromTop(0)->ToNumber()));
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_rect: {
			Assert(numArgs == 5);
			atto_fill(int(vm->FromTop(3)->ToNumber()), int(vm->FromTop(2)->ToNumber()), int(vm->FromTop(1)->ToNumber()), int(vm->FromTop(0)->ToNumber()));
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_color: {
			Assert(numArgs == 4);
			atto_color(vm->FromTop(2)->ToNumber(), vm->FromTop(1)->ToNumber(), vm->FromTop(0)->ToNumber());
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_line: {
			Assert(numArgs == 5);
			atto_line(int(vm->FromTop(3)->ToNumber()), int(vm->FromTop(2)->ToNumber()), int(vm->FromTop(1)->ToNumber()), int(vm->FromTop(0)->ToNumber()));
			vm->Drop(numArgs - 1);
			break;
		}
		case msg_random: {
			vm->Drop(numArgs);
			vm->PushPtr(new Number(double(rand()) / double(RAND_MAX)));
			break;
		}
		default: {
			return System::Receive(msg, numArgs, vm);
		}
	}
	return true;
}
